
#include <BFile>
#include <BCursor>
#include <BPainter>
#include <BKeyEvent>
#include <BMouseEvent>
#include <BStyleDocument>

#include "IGlobal.h"
#include "member_BWidget.h"
#include "member_BLayout.h"
#include "member_BDrag.h"
#include "member_BStyle.h"
#include "member_BPixmap.h"
#include "member_BObject.h"
#include "member_BEventFilter.h"

using namespace BWE;

#define member					(*(member_BWidget*)_ptr)
#define member_allocate()		_ptr = new member_BWidget(this)
#define member_release()		delete (member_BWidget*)_ptr

BWidget::BWidget(BWidget* parent)
{
	member_allocate();
	if (parent && parent != this)
		parent->addChild(this);
}
BWidget::BWidget(const BString& name, BWidget* parent) : BObject(name)
{
	member_allocate();
	if (parent && parent != this)
		parent->addChild(this);
}
BWidget::BWidget(const BWidget& other)
{
	member_allocate();
	this->copy(&other);
}
BWidget::~BWidget()
{
	for (int i = 0; i < app_windows.size(); i++)
	{
		IWindow* window = app_windows[i];
		if (window->hoverWidget == this)
			window->hoverWidget = 0;
		if (window->focusWidget == this)
			window->focusWidget = 0;
		if (window->popupWidgets.contain(this))
			window->popupWidgets.remove(this);
	}
	while (BWidget* child = member.children.last())
	{
		this->removeChild(child);
	}
	if (member.layouts.size() > 0)
	{
		for (int i = 0; i < member.layouts.size(); i++)
		{
			BLayout* layout = member.layouts[i];
			layout_member(layout)->setHost(0);
		}
		member.layouts.clear();
	}
	App_DetachWindow(this);
	member_release();
}

void BWidget::copy(const BWidget* other)
{
	object_member(this)->name = object_member(other)->name;

	member.samples = widget_member(other)->samples;
	member.opacity = widget_member(other)->opacity;
	member.layered = widget_member(other)->layered;

	member.title = widget_member(other)->title;
	member.icon = widget_member(other)->icon;
	member.tips = widget_member(other)->tips;
	member.frameless = widget_member(other)->frameless;
	member.visible = widget_member(other)->visible;
	member.modal = widget_member(other)->modal;
	member.floating = widget_member(other)->floating;
	member.droppable = widget_member(other)->droppable;
	member.focusable = widget_member(other)->focusable;
	member.pos = widget_member(other)->pos;
	member.size = widget_member(other)->size;
	member.minSize = widget_member(other)->minSize;
	member.maxSize = widget_member(other)->maxSize;
	member.fixedSize = widget_member(other)->fixedSize;
	member.sizePolicy = widget_member(other)->sizePolicy;

	member.styleSheet = widget_member(other)->styleSheet;
	member.style = widget_member(other)->style;

	member.border = widget_member(other)->border;
	member.perch = widget_member(other)->perch;
	member.margin = widget_member(other)->margin;

	if (widget_member(other)->cursor)
	{
		member.cursor = widget_member(other)->cursor->clone();
	}
	if (widget_member(other)->eventFilter)
	{
		member.eventFilter = widget_member(other)->eventFilter->clone();
	}

	for (int i = 0; i < widget_member(other)->children.size(); i++)
	{
		BWidget* widget = widget_member(other)->children[i];
		BWidget* child = widget->clone();
		member.children.append(child);
	}
	this->fresh();
}
BWidget* BWidget::clone() const
{
	return new BWidget(*this);
}

bool BWidget::actived() const
{
	return member.state.actived;
}
bool BWidget::hovered() const
{
	return member.state.hovered;
}
bool BWidget::popuped() const
{
	const BWidget* root = this->root();
	if (IWindow* window = widget_member(root)->window)
		return window->popupWidgets.contain(this);
	return false;
}
bool BWidget::fettered() const
{
	return member.upperLayout && member.upperLayout->enabled();
}

void BWidget::show()
{
	if (!member.parent && !member.pixmap)
	{
		if (!member.window)
		{
			App_AttachWindow(this);
		}
		member.window->showNormal();
	}
	this->setVisible(true);
}
void BWidget::hide()
{
	this->setVisible(false);
	if (member.window)
	{
		member.window->hideWindow();
		member.window->popup(this, false);
	}
}
void BWidget::popup()
{
	if (!member.parent && !member.pixmap)
	{
		show();
	}
	else if (!member.ignored())
	{
		this->setVisible(true);
		BWidget* root = this->root();
		if (IWindow* window = widget_member(root)->window)
		{
			if (root != this)
			{
				window->popup(this, true);
			}
		}
		else if (BPixmap* pixmap = widget_member(root)->pixmap)
		{
			pixmap_member(pixmap)->popup(this, true);
		}
	}
}
bool BWidget::raise()
{
	if (member.parent)
	{
		BWidgetHolderArray& children = widget_member(member.parent)->children;
		int pos = children.find(this);
		if (children.move(pos, children.size() - 1))
		{
			for (int i = pos; i < children.size(); i++)
			{
				BWidget* widget = children[i];
				widget->emit(Signal_OrderChanged, i);
			}
			this->fresh();
			return true;
		}
	}
	if (member.pixmap)
	{
		BWidgetHolderArray& widgets = pixmap_member(member.pixmap)->widgets;
		int pos = widgets.find(this);
		if (widgets.move(pos, widgets.size() - 1))
		{
			for (int i = pos; i < widgets.size(); i++)
			{
				BWidget* widget = widgets[i];
				widget->emit(Signal_OrderChanged, i);
			}
			this->fresh();
			return true;
		}
	}
	return false;
}
bool BWidget::lower()
{
	if (member.parent)
	{
		BWidgetHolderArray& children = widget_member(member.parent)->children;
		int pos = children.find(this);
		if (children.move(pos, 0))
		{
			for (int i = 0; i <= pos; i++)
			{
				BWidget* widget = children[i];
				widget->emit(Signal_OrderChanged, i);
			}
			this->fresh();
			return true;
		}
	}
	if (member.pixmap)
	{
		BWidgetHolderArray& widgets = pixmap_member(member.pixmap)->widgets;
		int pos = widgets.find(this);
		if (widgets.move(pos, 0))
		{
			for (int i = 0; i <= pos; i++)
			{
				BWidget* widget = widgets[i];
				widget->emit(Signal_OrderChanged, i);
			}
			this->fresh();
			return true;
		}
	}
	return false;
}
void BWidget::adjust()
{
	member.dirtyLayout();
	member.dirtyUpperLayout();
	this->fresh();
}
void BWidget::fresh() const
{
	if (!member.refresh)
	{
		member.refresh = true;
		BWidget* upper = member.parent;
		while (upper)
		{
			if (widget_member(upper)->layered)
				widget_member(upper)->refresh = true;
			upper = widget_member(upper)->parent;
		}
		if (BPixmap* pixmap = member.pixmap)
		{
			pixmap->dirty();
		}
	}
}
void BWidget::flush() const
{
	for (int i = 0; i < member.children.size(); i++)
	{
		BWidget* child = member.children[i];
		child->flush();
	}
	if (member.refresh)
	{
		BEvent event(Event_Fresh);
		member.procEvent(event);
		if (member.dirtyLayouts)
		{
			member.dirtyLayouts = false;
			member.adjustDirtyLayouts();
		}
	}
}

bool BWidget::setName(const BString& name)
{
	if (BObject::setName(name))
	{
		if (member.parent)
		{
			BStyle* style = widget_member(member.parent)->realStyle;
			if (style && style_member(style)->children.size())
			{
				member.dirtyStyle = true;
				this->fresh();
			}
		}
		return true;
	}
	return false;
}
bool BWidget::setEnabled(bool enabled)
{
	if (BObject::setEnabled(enabled))
	{
		member.state.enabled = object_member(this)->enabled;
		if (member.state.enabled)
		{
			BWidget* parent = member.parent;
			while (parent)
			{
				if (!widget_member(parent)->state.enabled)
				{
					member.state.enabled = false;
					break;
				}
				parent = widget_member(parent)->parent;
			}
		}
		member.freshEnabled(member.state.enabled);
		return true;
	}
	return false;
}

bool BWidget::setTitle(const BString& title)
{
	if (member.title != title)
	{
		member.title = title;
		member.freshTitle();
		emit(Signal_TitleChanged, title);
		return true;
	}
	return false;
}
const BString& BWidget::title() const
{
	return member.title;
}

bool BWidget::setIcon(BIcon* icon)
{
	if (member.icon != icon)
	{
		member.icon = icon;
		if (member.window)
		{
			member.window->setWindowIcon(icon);
		}
		emit(Signal_IconChanged, icon);
		return true;
	}
	return false;
}
const BIcon* BWidget::icon() const
{
	return member.icon;
}
BIcon* BWidget::icon()
{
	return member.icon;
}

void BWidget::setTips(const BString& tips)
{
	if (member.tips != tips)
	{
		member.tips = tips;
		if (member.visible && member.state.hovered)
		{
			BWidget* root = this->root();
			if (IWindow* window = widget_member(root)->window)
			{
				window->refresh = true;
				window->tipsBoard.dirty = true;
			}
		}
	}
}
const BString& BWidget::tips() const
{
	return member.tips;
}
const BString& BWidget::realTips() const
{
	return member.tips;
}

void BWidget::setFrameless(bool frameless)
{
	if (member.frameless = frameless)
	{
		member.frameless = frameless;
		if (member.window)
		{
			member.window->setFrameless(frameless);
		}
		emit(Signal_FramelessChanged, frameless);
	}
}
bool BWidget::frameless() const
{
	return member.frameless;
}

void BWidget::setSamples(int samples)
{
	samples = bClamp(samples, 0, 32);
	if (member.samples != samples)
	{
		member.samples = samples;
		if (member.window)
		{
			member.window->resized = true;
		}
		emit(Signal_SamplesChanged, samples);
		this->fresh();
	}
}
int BWidget::samples() const
{
	return member.samples;
}

bool BWidget::setVisible(bool visible)
{
	if (member.visible != visible)
	{
		member.visible = visible;
		if (BWidget* root = this->root())
		{
			if (widget_member(root)->window)
			{
				if (!member.visible)
					widget_member(root)->window->popup(this, false);
				widget_member(root)->window->refresh = true;
			}
		}
		if (member.upperLayout)
		{
			member.dirtyUpperLayout();
		}
		if (visible && member.dirtyStyle)
		{
			member.dirtyStyle = false;
			BEvent styleEvent(Event_Style);
			member.dispenseStyles(styleEvent);
		}
		if (member.visible)
		{
			BEvent event(Event_Show);
			member.procEvent(event);
		}
		else
		{
			BEvent event(Event_Hide);
			member.procEvent(event);
		}
		return true;
	}
	return false;
}
bool BWidget::visible() const
{
	return member.visible;
}

void BWidget::setFloating(bool floating)
{
	if (member.floating != floating)
	{
		member.floating = floating;
		this->fresh();
	}
}
bool BWidget::floating() const
{
	return member.floating;
}

void BWidget::setLayered(bool layered)
{
	if (member.layered != layered)
	{
		member.layered = layered;
		this->fresh();
	}
}
bool BWidget::layered() const
{
	return member.layered;
}

void BWidget::setOpacity(BByte opacity)
{
	if (member.opacity != opacity)
	{
		member.opacity = opacity;
		this->fresh();
	}
}
BByte BWidget::opacity() const
{
	return member.opacity;
}

void BWidget::setModal(bool modal)
{
	if (member.modal != modal)
	{
		member.modal = modal;
	}
}
bool BWidget::modal() const
{
	return member.modal;
}

void BWidget::setDroppable(bool droppable)
{
	if (member.droppable != droppable)
	{
		member.droppable = droppable;
	}
}
bool BWidget::droppable() const
{
	return member.droppable;
}

void BWidget::setFocusable(bool focusable)
{
	if (member.focusable != focusable)
	{
		member.focusable = focusable;
		if (member.focused)
			this->setFocused(false);
	}
}
bool BWidget::focusable() const
{
	return member.focusable;
}

bool BWidget::setFocused(bool focused)
{
	if (focused && !this->enabled())
		return false;
	if (!member.focusable)
		return false;
	if (member.focused != focused)
	{
		BWidget* root = this->root();
		if (root && widget_member(root)->window)
		{
			if (focused)
				widget_member(root)->window->focus(this);
			else
				widget_member(root)->window->focus(member.parent);
		}
		this->fresh();
		return true;
	}
	return false;
}
bool BWidget::focused() const
{
	return member.focused;
}

void BWidget::move(const BPoint& offset)
{
	setPos(member.pos + offset);
}
void BWidget::move(int x, int y)
{
	setPos(member.pos + BPoint(x, y));
}

void BWidget::setPos(int x, int y)
{
	setPos(BPoint(x, y));
}
void BWidget::setPos(const BPoint& pos)
{
	if (member.pos != pos)
	{
		if (member.window && !member.window->setWindowPos(pos))
			return;
		member.pos = pos;
		BEvent moveEvent(Event_Move);
		member.procEvent(moveEvent);
		BWidget* root = this->root();
		if (root != this && widget_member(root)->window)
		{
			widget_member(root)->window->refresh = true;
		}
	}
}
const BPoint& BWidget::pos() const
{
	return member.pos;
}

bool BWidget::setSize(int width, int height)
{
	return setSize(BSize(width, height));
}
bool BWidget::setSize(const BSize& size)
{
	BSize temp = size;
	temp.limit(member.minSize, member.maxSize);
	const BSize& fixed = member.fixedSize;
	const BSizePolicy& policy = member.sizePolicy;
	if (policy.widthPolicy() & Policy_Fixed)
	{
		if (temp.width() > fixed.width() && !(policy.widthPolicy() & Policy_Expanding))
			temp.width() = fixed.width();
		if (temp.width() < fixed.width() && !(policy.widthPolicy() & Policy_Shrinking))
			temp.width() = fixed.width();
	}
	if (policy.heightPolicy() & Policy_Fixed)
	{
		if (temp.height() > fixed.height() && !(policy.widthPolicy() & Policy_Expanding))
			temp.height() = fixed.height();
		if (temp.height() < fixed.height() && !(policy.widthPolicy() & Policy_Shrinking))
			temp.height() = fixed.height();
	}
	if (member.size != temp)
	{
		member.size = temp;
		member.dirtyRects = true;
		member.freshRects();
		member.dirtyLayout();

		BEvent resizeEvent(Event_Resize);
		resizeEvent.setValue(member.size);
		member.procEvent(resizeEvent);

		if (member.window)
		{
			member.window->setWindowSize(member.size);
		}
		return true;
	}
	return false;
}
const BSize& BWidget::size() const
{
	return member.size;
}

void BWidget::setWidth(int width)
{
	int height = member.size.height();
	setSize(BSize(width, height));
}
int BWidget::width() const
{
	return member.size.width();
}

void BWidget::setHeight(int height)
{
	int width = member.size.width();
	BSize size(width, height);
	setSize(size);
}
int BWidget::height() const
{
	return member.size.height();
}

void BWidget::setRect(const BRect& rect)
{
	BPoint pos = rect.pos();
	setPos(pos);
	BSize size = rect.size();
	setSize(size);
}
void BWidget::setRect(int x, int y, int width, int height)
{
	setPos(BPoint(x, y));
	setSize(BSize(width, height));
}
BRect BWidget::rect() const
{
	return BRect(member.pos, member.size);
}
BRect BWidget::rect(Part part) const
{
	switch (part)
	{
	case Part_None:
		return BRect(member.size);
	case Part_Top:
		return member.rectTop;
	case Part_Left:
		return member.rectLeft;
	case Part_Right:
		return member.rectRight;
	case Part_Bottom:
		return member.rectBottom;
	case Part_Center:
		return member.rectCenter;
	case Part_Title:
		return member.rectTitle;
	case Part_LeftTop:
		return member.rectLeftTop;
	case Part_LeftBottom:
		return member.rectLeftBottom;
	case Part_RightTop:
		return member.rectRightTop;
	case Part_RightBottom:
		return member.rectRightBottom;
	default:
		break;
	}
	BRect rect;
	if (part & Part_Center)
	{
		rect = member.rectCenter;
		if (part & Part_Top)
			rect.expand(member.rectTop);
		if (part & Part_Left)
			rect.expand(member.rectLeft);
		if (part & Part_Right)
			rect.expand(member.rectRight);
		if (part & Part_Bottom)
			rect.expand(member.rectBottom);
	}
	return rect;
}

void BWidget::setCenterSize(int cwidth, int cheight)
{
	int b = member.border;
	const BPerch& p = member.perch;
	const BMargin& m = member.margin;

	int width = b + p.left() + m.left() + cwidth + m.right() + p.right() + b;
	int height = b + p.top() + m.top() + cheight + m.bottom() + p.bottom() + b;

	this->setSize(width, height);
}
void BWidget::setCenterSize(const BSize& centerSize)
{
	setCenterSize(centerSize.width(), centerSize.height());
}
BSize BWidget::centerSize() const
{
	return member.rectCenter.size();
}
const BRect& BWidget::centerRect() const
{
	return member.rectCenter;
}

void BWidget::setAbsolutePos(const BPoint& absolutePos)
{
	setPos(absolutePos - this->absolutePos());
}
void BWidget::setAbsolutePos(int absoluteX, int absoluteY)
{
	setAbsolutePos(BPoint(absoluteX, absoluteY));
}
BPoint BWidget::absolutePos() const
{
	return globalPos() - root()->pos();
}

void BWidget::setAbsoluteRect(const BRect& absoluteRect)
{
	BPoint localPoint;
	if (member.parent)
	{
		localPoint = member.parent->absolutePos();
	}
	BPoint pos = absoluteRect.pos() - localPoint;
	BSize size = absoluteRect.size();
	setPos(pos);
	setSize(size);
}
void BWidget::setAbsoluteRect(int x, int y, int width, int height)
{
	BPoint pos = BPoint(x, y) - absolutePos();
	BSize size(width, height);
	setPos(pos);
	setSize(size);
}
BRect BWidget::absoluteRect() const
{
	return BRect(absolutePos(), member.size);
}

void BWidget::setGlobalPos(const BPoint& globalPos)
{

}
void BWidget::setGlobalPos(int globalX, int globalY)
{
	setGlobalPos(BPoint(globalX, globalY));
}
BPoint BWidget::globalPos() const
{
	BPoint pos = member.pos;
	const BWidget* parent = member.parent;
	while (parent)
	{
		pos += parent->pos();
		parent = parent->parent();
	}
	return pos;
}

void BWidget::setGlobalRect(const BRect& absoluteRect)
{
	BPoint glPos = absoluteRect.pos();
	BSize size = absoluteRect.size();
	setGlobalPos(glPos);
	setSize(size);
}
void BWidget::setGlobalRect(int x, int y, int width, int height)
{
	BPoint glPos(x, y);
	BSize size(width, height);
	setGlobalPos(glPos);
	setSize(size);
}
BRect BWidget::globalRect() const
{
	BPoint glPos = this->globalPos();
	return BRect(glPos, member.size);
}

BPoint BWidget::mapTo(const BWidget* widget, const BPoint& point) const
{
	if (!widget)
		return BPoint();

	BPoint downPoint = point;
	const BWidget* dw = widget;
	while (dw)
	{
		if (dw == this)
			return downPoint;
		downPoint -= dw->pos();
		dw = dw->parent();
	}

	BPoint upPoint = point;
	const BWidget* uw = this;
	while (uw)
	{
		if (uw == widget)
			return upPoint;
		upPoint += uw->pos();
		uw = uw->parent();
	}

	const BWidget* parent = widget;
	while (parent)
	{
		upPoint -= parent->pos();
		parent = parent->parent();
	}
	return upPoint;
}
BPoint BWidget::mapFrom(const BWidget* widget, const BPoint& point) const
{
	if (!widget)
		return BPoint();

	BPoint downPoint = point;
	const BWidget* dw = this;
	while (dw)
	{
		if (dw == widget)
			return downPoint;
		downPoint -= dw->pos();
		dw = dw->parent();
	}

	BPoint upPoint = point;
	const BWidget* uw = widget;
	while (uw)
	{
		if (uw == this)
			return upPoint;
		upPoint += uw->pos();
		uw = uw->parent();
	}

	const BWidget* parent = this;
	while (parent)
	{
		upPoint -= parent->pos();
		parent = parent->parent();
	}
	return upPoint;
}

BRect BWidget::mapTo(const BWidget* widget, const BRect& rect) const
{
	if (!widget)
		return BRect();

	BRect downRect = rect;
	const BWidget* dw = widget;
	while (dw)
	{
		if (dw == this)
			return downRect;
		downRect -= dw->pos();
		dw = dw->parent();
	}

	BRect upRect = rect;
	const BWidget* uw = this;
	while (uw)
	{
		if (uw == widget)
			return upRect;
		upRect += uw->pos();
		uw = uw->parent();
	}

	const BWidget* parent = widget;
	while (parent)
	{
		upRect -= parent->pos();
		parent = parent->parent();
	}
	return upRect;
}
BRect BWidget::mapFrom(const BWidget* widget, const BRect& rect) const
{
	if (!widget)
		return BRect();

	BRect downRect = rect;
	const BWidget* down = this;
	while (down)
	{
		if (down == widget)
			return downRect;
		downRect -= down->pos();
		down = down->parent();
	}

	BRect upRect = rect;
	const BWidget* up = widget;
	while (up)
	{
		if (up == this)
			return upRect;
		upRect += up->pos();
		up = up->parent();
	}

	const BWidget* parent = this;
	while (parent)
	{
		upRect -= parent->pos();
		parent = parent->parent();
	}
	return upRect;
}

void BWidget::setMinWidth(int minWidth)
{
	setMinSize(BSize(minWidth, member.minSize.height()));
}
int BWidget::minWidth() const
{
	return member.minSize.width();
}

void BWidget::setMinHeight(int minHeight)
{
	setMinSize(BSize(member.minSize.width(), minHeight));
}
int BWidget::minHeight() const
{
	return member.minSize.height();
}

void BWidget::setMinSize(int minWidth, int minHeight)
{
	setMinSize(BSize(minWidth, minHeight));
}
void BWidget::setMinSize(const BSize& minSize)
{
	if (member.minSize != minSize)
	{
		member.minSize = minSize;
		this->setSize(member.size);
	}
}
const BSize& BWidget::minSize() const
{
	return member.minSize;
}

void BWidget::setMaxWidth(int maxWidth)
{
	setMaxSize(BSize(maxWidth, member.maxSize.height()));
}
int BWidget::maxWidth() const
{
	return member.maxSize.width();
}

void BWidget::setMaxHeight(int maxHeight)
{
	setMaxSize(BSize(member.maxSize.width(), maxHeight));
}
int BWidget::maxHeight() const
{
	return member.maxSize.height();
}

void BWidget::setMaxSize(int maxWidth, int maxHeight)
{
	setMaxSize(BSize(maxWidth, maxHeight));
}
void BWidget::setMaxSize(const BSize& maxSize)
{
	if (member.maxSize != maxSize)
	{
		member.maxSize = maxSize;
		this->setSize(member.size);
	}
}
const BSize& BWidget::maxSize() const
{
	return member.maxSize;
}

void BWidget::setFixedWidth(int fixedWidth)
{
	if (member.fixedSize.width() != fixedWidth)
	{
		member.fixedSize.width() = fixedWidth;
		member.sizePolicy.widthPolicy() |= Policy_Fixed;
		this->adjust();
	}
}
int BWidget::fixedWidth() const
{
	return member.fixedSize.width();
}

void BWidget::setFixedHeight(int fixedHeight)
{
	if (member.fixedSize.height() != fixedHeight)
	{
		member.fixedSize.height() = fixedHeight;
		member.sizePolicy.heightPolicy() = Policy_Fixed;
		this->adjust();
	}
}
int BWidget::fixedHeight() const
{
	return member.fixedSize.height();
}

void BWidget::setFixedSize(int fixedWidth, int fixedHeight)
{
	setFixedSize(BSize(fixedWidth, fixedHeight));
}
void BWidget::setFixedSize(const BSize& fixedSize)
{
	if (member.fixedSize != fixedSize)
	{
		member.fixedSize = fixedSize;
		member.sizePolicy.widthPolicy() |= Policy_Fixed;
		member.sizePolicy.heightPolicy() |= Policy_Fixed;
		this->adjust();
	}
}
const BSize& BWidget::fixedSize() const
{
	return member.fixedSize;
}

void BWidget::setWidthPolicy(Policy widthPolicy)
{
	BSizePolicy sizePolicy(widthPolicy, member.sizePolicy.heightPolicy());
	setSizePolicy(sizePolicy);
}
Policy BWidget::widthPolicy() const
{
	return member.sizePolicy.widthPolicy();
}

void BWidget::setHeightPolicy(Policy heightPolicy)
{
	BSizePolicy sizePolicy(member.sizePolicy.widthPolicy(), heightPolicy);
	setSizePolicy(sizePolicy);
}
Policy BWidget::heightPolicy() const
{
	return member.sizePolicy.heightPolicy();
}

void BWidget::setSizePolicy(Policy widthPolicy, Policy heightPolicy)
{
	setSizePolicy(BSizePolicy(widthPolicy, heightPolicy));
}
void BWidget::setSizePolicy(const BSizePolicy& sizePolicy)
{
	if (member.sizePolicy != sizePolicy)
	{
		member.sizePolicy = sizePolicy;
		this->adjust();
	}
}
const BSizePolicy& BWidget::sizePolicy() const
{
	return member.sizePolicy;
}

void BWidget::setBorder(int border)
{
	if (member.border != border)
	{
		member.border = border;
		member.freshRects();
		this->adjust();

		BEvent resizeEvent(Event_Resize);
		resizeEvent.setValue(member.size);
		member.procEvent(resizeEvent);
	}
}
int BWidget::border() const
{
	return member.border;
}

void BWidget::setPerch(int left, int top, int right, int bottom)
{
	setPerch(BPerch(left, top, right, bottom));
}
void BWidget::setPerch(const BPerch& perch)
{
	BPerch temp = perch;
	for (int i = 0; i < member.layouts.size(); i++)
	{
		BLayout* layout = member.layouts[i];
		Part part = layout->part();
		if (temp.top() < 0 && (part == Part_Top && layout->visible()))
			temp.top() = member.perch.top();
		if (temp.bottom() < 0 && (part == Part_Bottom && layout->visible()))
			temp.bottom() = member.perch.bottom();
		if (temp.left() < 0 && (part == Part_Left && layout->visible()))
			temp.left() = member.perch.left();
		if (temp.right() < 0 && (part == Part_Right && layout->visible()))
			temp.right() = member.perch.right();
	}
	if (member.perch != temp)
	{
		member.perch = temp;
		member.freshRects();
		this->adjust();

		BEvent resizeEvent(Event_Resize);
		resizeEvent.setValue(member.size);
		member.procEvent(resizeEvent);
	}
}
const BPerch& BWidget::perch() const
{
	return member.perch;
}

void BWidget::setPerch(PartFlag part, int value)
{
	BPerch perch = member.perch;
	switch (part)
	{
	case Part_Top:
		perch.top() = value;
		break;
	case Part_Left:
		perch.left() = value;
		break;
	case Part_Right:
		perch.right() = value;
		break;
	case Part_Bottom:
		perch.bottom() = value;
		break;
	default:
		return;
	}
	this->setPerch(perch);
}
int BWidget::perch(PartFlag part) const
{
	switch (part)
	{
	case Part_Top:
		return member.perch.top();
	case Part_Left:
		return member.perch.left();
	case Part_Right:
		return member.perch.right();
	case Part_Bottom:
		return member.perch.bottom();
	default:
		return -1;
	}
}

void BWidget::setMargin(int left, int top, int right, int bottom)
{
	BMargin margin(left, top, right, bottom);
	setMargin(margin);
}
void BWidget::setMargin(const BMargin& margin)
{
	if (member.margin != margin)
	{
		member.margin = margin;
		member.freshRects();
		this->adjust();

		BEvent resizeEvent(Event_Resize);
		resizeEvent.setValue(member.size);
		member.procEvent(resizeEvent);
	}
}
const BMargin& BWidget::margin() const
{
	return member.margin;
}

void BWidget::setMargin(PartFlag part, int value)
{
	BMargin margin = member.margin;
	switch (part)
	{
	case Part_Left:
		margin.left() = value;
		break;
	case  Part_Top:
		margin.top() = value;
		break;
	case  Part_Right:
		margin.right() = value;
		break;
	case  Part_Bottom:
		margin.bottom() = value;
		break;
	default:
		return;
	}
	this->setMargin(margin);
}
int BWidget::margin(PartFlag part) const
{
	switch (part)
	{
	case Part_Left:
		return member.margin.left();
	case Part_Top:
		return member.margin.top();
	case Part_Right:
		return member.margin.right();
	case Part_Bottom:
		return member.margin.bottom();
	default:
		return -1;
	}
}

void BWidget::setRadius(const BSize& radius, PartFlag part)
{
	bool changed = false;
	if (member.round.empty())
	{
		member.round = new IRound();
		changed = true;
	}
	if (part & Part_Left && part & Part_Top)
	{
		if (member.radiusLeftTop != radius)
		{
			member.radiusLeftTop = radius;
			changed = true;
		}
	}
	if (part & Part_Left && part & Part_Bottom)
	{
		if (member.radiusLeftBottom != radius)
		{
			member.radiusLeftBottom = radius;
			changed = true;
		}
	}
	if (part & Part_Right && part & Part_Top)
	{
		if (member.radiusRightTop != radius)
		{
			member.radiusRightTop = radius;
			changed = true;
		}
	}
	if (part & Part_Right && part & Part_Bottom)
	{
		if (member.radiusRightBottom != radius)
		{
			member.radiusRightBottom = radius;
			changed = true;
		}
	}
	if (changed)
	{
		this->fresh();
	}
}
void BWidget::setRadius(const BSize& leftTop, const BSize& rightTop, const BSize& rightBottom, const BSize& leftBottom)
{
	if (member.round.empty() && leftTop.empty() && rightTop.empty() && rightBottom.empty() && leftBottom.empty())
		return;
	bool changed = false;
	if (member.round.empty())
	{
		member.round = new IRound();
		changed = true;
	}
	if (member.radiusLeftTop != leftTop)
	{
		member.radiusLeftTop = leftTop;
		changed = true;
	}
	if (member.radiusRightTop != rightTop)
	{
		member.radiusRightTop = rightTop;
		changed = true;
	}
	if (member.radiusRightBottom != rightBottom)
	{
		member.radiusRightBottom = rightBottom;
		changed = true;
	}
	if (member.radiusLeftBottom != leftBottom)
	{
		member.radiusLeftBottom = leftBottom;
		changed = true;
	}
	if (changed)
	{
		this->fresh();
	}
}
BSize BWidget::radius(PartFlag part)
{
	if (part == Part_LeftTop)
		return member.radiusLeftTop;
	if (part == Part_RightTop)
		return member.radiusRightTop;
	if (part == Part_RightBottom)
		return member.radiusRightBottom;
	if (part == Part_LeftBottom)
		return member.radiusLeftBottom;
	return BSize();
}

void BWidget::setCursor(CursorType type)
{
	if (type == Cursor_None)
	{
		setCursor(0);
	}
	else
	{
		BCursor* cursor = new BCursor(type);
		setCursor(cursor);
	}
}
void BWidget::setCursor(BCursor* cursor)
{
	if (member.cursor != cursor)
	{
		member.cursor = cursor;
		BWidget* root = this->root();
		if (IWindow* window = widget_member(root)->window)
			window->refresh = true;
		if (BPixmap* pixmap = widget_member(root)->pixmap)
			pixmap->dirty();
		emit(Signal_CursorChanged, member.cursor);
	}
}
BCursor* BWidget::cursor() const
{
	return member.cursor;
}

void BWidget::setFont(const BString& family, int size)
{
	if (family.empty())
	{
		setFont(0);
	}
	else
	{
		BFont* font = new BFont(family, size);
		setFont(font);
	}
}
void BWidget::setFont(BFont* font)
{
	if (member.style.empty() && font)
	{
		member.style = new BStyle();
	}
	if (member.style)
	{
		member.style->setFont(font);
		member.dirtyStyle = true;
		this->fresh();
	}
}
BFont* BWidget::font() const
{
	if (member.style)
		return member.style->font();
	return 0;
}

const BFont* BWidget::realFont() const
{
	if (member.realStyle)
		return member.realStyle->font();
	return app_style->font();
}

void BWidget::setStyleSheet(const BString& styleSheet)
{
	if (member.styleSheet != styleSheet)
	{
		member.styleSheet = styleSheet;
		BStyle* style = 0;
		if (styleSheet.size())
		{
			style = new BStyle();
			BStyleDocument document;
			if (BFile::Exist(styleSheet))
			{
				document.setPath(styleSheet.path());
				document.load(styleSheet, style);
			}
			else
			{
				document.setPath(BString());
				document.read(styleSheet, style);
			}
		}
		setStyle(style);
		this->fresh();
	}
}
const BString& BWidget::styleSheet() const
{
	return member.styleSheet;
}

bool BWidget::setStyle(BStyle* style)
{
	if (member.style != style)
	{
		member.style = style;
		member.dirtyStyle = true;
		this->fresh();
	}
	return true;
}
BStyle* BWidget::style() const
{
	return member.style;
}

const BStyle* BWidget::realStyle() const
{
	if (member.realStyle)
		return member.realStyle;
	return app_style;
}
void BWidget::clearStyle()
{
	if (member.style)
	{
		member.style = 0;
		member.styleSheet.clear();
		member.dirtyStyle = true;
		this->fresh();
	}
	if (member.realStyle)
	{
		member.realStyle = 0;
		member.dirtyStyle = true;
		this->fresh();
	}
}

bool BWidget::setLayout(BLayout* layout, PartFlag part)
{
	if (!layout)
		return false;
	if (layout_member(layout)->host != this)
	{
		member.layouts.append(layout);
		layout_member(layout)->part = part;
		layout_member(layout)->setHost(this);
		this->adjust();
	}
	return true;
}
BLayout* BWidget::layout(PartFlag part)
{
	for (int i = 0; i < member.layouts.size(); i++)
	{
		BLayout* layout = member.layouts[i];
		if (layout_member(layout)->part == part)
			return layout;
	}
	return 0;
}
const BLayout* BWidget::layout(PartFlag part) const
{
	for (int i = 0; i < member.layouts.size(); i++)
	{
		const BLayout* layout = member.layouts[i];
		if (layout_member(layout)->part == part)
			return layout;
	}
	return 0;
}

bool BWidget::addLayout(BLayout* layout)
{
	if (!layout)
		return false;
	if (layout_member(layout)->host != this)
	{
		member.layouts.append(layout);
		layout_member(layout)->setHost(this);
		this->adjust();
	}
	return true;
}
bool BWidget::removeLayout(BLayout* layout)
{
	if (layout == 0 || layout_member(layout)->host != this)
		return false;
	if (BLayout* parent = layout->parent())
	{
		parent->remove(layout);
		return true;
	}
	for (int i = 0; i < member.children.size(); i++)
	{
		BWidget* child = member.children[i];
		if (layout->contain(child))
		{
			widget_member(child)->parent = 0;
			member.children.remove(i--);
		}
	}
	layout_member(layout)->setHost(0);
	if (layout_member(layout)->part)
	{
		this->adjust();
	}
	member.layouts.remove(layout);
	return true;
}
bool BWidget::containLayout(const BLayout* layout) const
{
	if (layout == 0 || layout_member(layout)->host != this)
		return false;
	return member.layouts.contain(layout);
}

int BWidget::layoutCount() const
{
	return member.layouts.size();
}
BLayout* BWidget::layout(int index)
{
	return member.layouts(index);
}
const BLayout* BWidget::layout(int index) const
{
	return member.layouts(index);
}

BLayout* BWidget::layout(const BString& name)
{
	if (name.empty())
		return 0;
	for (int i = 0; i < member.layouts.size(); i++)
	{
		BLayout* layout = member.layouts[i];
		if (layout->name() == name)
			return layout;
		BLayout* ret = layout->findLayout(name);
		if (ret)
			return ret;
	}
	return 0;
}
const BLayout* BWidget::layout(const BString& name) const
{
	if (name.empty())
		return 0;
	for (int i = 0; i < member.layouts.size(); i++)
	{
		BLayout* layout = member.layouts[i];
		if (layout->name() == name)
			return layout;
		BLayout* ret = layout->findLayout(name);
		if (ret)
			return ret;
	}
	return 0;
}

void BWidget::setEventFilter(BEventFilter* eventFilter)
{
	if (member.eventFilter != eventFilter)
	{
		BHolder<BEventFilter> holder(member.eventFilter);
		member.eventFilter = eventFilter;
		if (BEventFilter* filter = holder)
			filter_member(filter)->setWidget(0);
		if (eventFilter)
			filter_member(eventFilter)->setWidget(this);
	}
}
const BEventFilter* BWidget::eventFilter() const
{
	return member.eventFilter;
}
BEventFilter* BWidget::eventFilter()
{
	return member.eventFilter;
}

BSize BWidget::preferSize(int cwidth, int cheight) const
{
	return preferSize(BSize(cwidth, cheight));
}
BSize BWidget::preferSize(const BSize& csize) const
{
	BSize leftSize;
	BSize topSize;
	BSize rightSize;
	BSize bottomSize;
	BSize centerSize = csize;
	for (int i = 0; i < member.layouts.size(); i++)
	{
		BLayout* layout = member.layouts[i];
		if (!layout_member(layout)->visible)
			continue;
		if (!layout_member(layout)->part)
			continue;
		BSize fixSize = layout->fixedSize();
		BSize preSize = layout->preferSize();
		BSizePolicy sizePolicy = layout->sizePolicy();
		if (layout_member(layout)->part == Part_Title)
		{
			topSize.height() = preSize.height();
			if (sizePolicy.widthPolicy() & Policy_Fixed)
				centerSize.width() = bMax(centerSize.width(), fixSize.width());
			if (sizePolicy.widthPolicy() & Policy_Preferred)
				centerSize.width() = bMax(centerSize.width(), preSize.width());
		}
		if (layout_member(layout)->part == Part_Top)
		{
			topSize.height() = preSize.height();
			if (sizePolicy.widthPolicy() & Policy_Fixed)
				centerSize.width() = bMax(centerSize.width(), fixSize.width());
			if (sizePolicy.widthPolicy() & Policy_Preferred)
				centerSize.width() = bMax(centerSize.width(), preSize.width());
		}
		if (layout_member(layout)->part == Part_Left)
		{
			leftSize.width() = preSize.width();
			if (sizePolicy.widthPolicy() & Policy_Fixed)
				centerSize.height() = bMax(centerSize.height(), fixSize.height());
			if (sizePolicy.widthPolicy() & Policy_Preferred)
				centerSize.height() = bMax(centerSize.height(), preSize.height());
		}
		if (layout_member(layout)->part == Part_Right)
		{
			rightSize.width() = preSize.width();
			if (sizePolicy.widthPolicy() & Policy_Fixed)
				centerSize.height() = bMax(centerSize.height(), fixSize.height());
			if (sizePolicy.widthPolicy() & Policy_Preferred)
				centerSize.height() = bMax(centerSize.height(), preSize.height());
		}
		if (layout_member(layout)->part == Part_Bottom)
		{
			bottomSize.height() = preSize.height();
			if (sizePolicy.widthPolicy() & Policy_Fixed)
				centerSize.width() = bMax(centerSize.width(), fixSize.width());
			if (sizePolicy.widthPolicy() & Policy_Preferred)
				centerSize.width() = bMax(centerSize.width(), preSize.width());
		}
		if (layout_member(layout)->part == Part_Center)
		{
			if (sizePolicy.widthPolicy() & Policy_Fixed)
				centerSize.width() = bMax(centerSize.width(), fixSize.width());
			if (sizePolicy.widthPolicy() & Policy_Preferred)
				centerSize.width() = bMax(centerSize.width(), preSize.width());
			if (sizePolicy.heightPolicy() & Policy_Fixed)
				centerSize.height() = bMax(centerSize.height(), fixSize.height());
			if (sizePolicy.heightPolicy() & Policy_Preferred)
				centerSize.height() = bMax(centerSize.height(), preSize.height());
		}
	}

	BPerch p = member.perch;
	if (p.top() < topSize.height())
		p.top() = topSize.height();
	if (p.left() < leftSize.width())
		p.left() = leftSize.width();
	if (p.right() < rightSize.width())
		p.right() = rightSize.width();
	if (p.bottom() < bottomSize.height())
		p.bottom() = bottomSize.height();

	const BMargin& m = member.margin;
	int b = member.border;
	int pwidth = b + p.left() + m.left() + m.right() + p.right() + b + centerSize.width();
	int pheight = b + p.top() + m.top() + m.bottom() + p.bottom() + b + centerSize.height();

	if (member.sizePolicy.widthPolicy() == Policy_Fixed)
	{
		pwidth = member.fixedSize.width();
	}
	else
	{
		if (pwidth < topSize.width())
			pwidth = topSize.width();
		if (pwidth < bottomSize.width())
			pwidth = bottomSize.width();
	}

	if (member.sizePolicy.heightPolicy() == Policy_Fixed)
	{
		pheight = member.fixedSize.height();
	}
	else
	{
		if (pheight < leftSize.height())
			pheight = leftSize.height();
		if (pheight < rightSize.height())
			pheight = rightSize.height();
	}

	return BSize(pwidth, pheight);
}
BSize BWidget::preferSize(PartFlag part) const
{
	if (part == Part_All)
		return preferSize(BSize());

	BSize titleSize;
	BSize topSize;
	BSize leftSize;
	BSize rightSize;
	BSize bottomSize;
	BSize centerSize;
	for (int i = 0; i < member.layouts.size(); i++)
	{
		BLayout* layout = member.layouts[i];
		if (!layout_member(layout)->visible)
			continue;
		if (!layout_member(layout)->part)
			continue;
		BSize fixSize = layout->fixedSize();
		BSize preSize = layout->preferSize();
		BSizePolicy sizePolicy = layout->sizePolicy();
		if (layout_member(layout)->part == Part_Title)
		{
			titleSize.height() = preSize.height();
			if (sizePolicy.widthPolicy() & Policy_Fixed)
				centerSize.width() = bMax(centerSize.width(), fixSize.width());
			if (sizePolicy.widthPolicy() & Policy_Preferred)
				centerSize.width() = bMax(centerSize.width(), preSize.width());
			if (sizePolicy.heightPolicy() & Policy_Fixed)
				centerSize.height() = bMax(centerSize.height(), fixSize.height());
			if (sizePolicy.heightPolicy() & Policy_Preferred)
				centerSize.height() = bMax(centerSize.height(), preSize.height());
		}
		if (layout_member(layout)->part == Part_Top)
		{
			topSize.height() = preSize.height();
			if (sizePolicy.widthPolicy() & Policy_Fixed)
				centerSize.width() = bMax(centerSize.width(), fixSize.width());
			if (sizePolicy.widthPolicy() & Policy_Preferred)
				centerSize.width() = bMax(centerSize.width(), preSize.width());
		}
		if (layout_member(layout)->part == Part_Left)
		{
			leftSize.width() = preSize.width();
			if (sizePolicy.widthPolicy() & Policy_Fixed)
				centerSize.height() = bMax(centerSize.height(), fixSize.height());
			if (sizePolicy.widthPolicy() & Policy_Preferred)
				centerSize.height() = bMax(centerSize.height(), preSize.height());
		}
		if (layout_member(layout)->part == Part_Right)
		{
			rightSize.width() = preSize.width();
			if (sizePolicy.widthPolicy() & Policy_Fixed)
				centerSize.height() = bMax(centerSize.height(), fixSize.height());
			if (sizePolicy.widthPolicy() & Policy_Preferred)
				centerSize.height() = bMax(centerSize.height(), preSize.height());
		}
		if (layout_member(layout)->part == Part_Bottom)
		{
			bottomSize.height() = preSize.height();
			if (sizePolicy.widthPolicy() & Policy_Fixed)
				centerSize.width() = bMax(centerSize.width(), fixSize.width());
			if (sizePolicy.widthPolicy() & Policy_Preferred)
				centerSize.width() = bMax(centerSize.width(), preSize.width());
		}
		if (layout_member(layout)->part == Part_Center)
		{
			if (sizePolicy.widthPolicy() & Policy_Fixed)
				centerSize.width() = bMax(centerSize.width(), fixSize.width());
			if (sizePolicy.widthPolicy() & Policy_Preferred)
				centerSize.width() = bMax(centerSize.width(), preSize.width());
			if (sizePolicy.heightPolicy() & Policy_Fixed)
				centerSize.height() = bMax(centerSize.height(), fixSize.height());
			if (sizePolicy.heightPolicy() & Policy_Preferred)
				centerSize.height() = bMax(centerSize.height(), preSize.height());
		}

		if (layout_member(layout)->part & Part_Top && topSize.height() < preSize.height())
			topSize.height() = preSize.height();
		if (layout_member(layout)->part & Part_Left && leftSize.width() < preSize.width())
			leftSize.width() = preSize.width();
		if (layout_member(layout)->part & Part_Right && rightSize.width() < preSize.width())
			rightSize.width() = preSize.width();
		if (layout_member(layout)->part & Part_Bottom && bottomSize.height() < preSize.height())
			bottomSize.height() = preSize.height();

	}

	switch (part)
	{
	case Part_Top:
		return topSize;
	case Part_Left:
		return leftSize;
	case Part_Right:
		return rightSize;
	case Part_Bottom:
		return bottomSize;
	case Part_LeftTop:
		return BSize(leftSize.width(), topSize.height());
	case Part_RightTop:
		return BSize(rightSize.width(), topSize.height());
	case Part_LeftBottom:
		return BSize(leftSize.width(), bottomSize.height());
	case Part_RightBottom:
		return BSize(rightSize.width(), bottomSize.height());
	case Part_Center:
		return centerSize;
	}
	return BSize(0, 0);
}

BSize BWidget::shellSize() const
{
	int b = member.border;
	const BPerch& p = member.perch;
	const BMargin& m = member.margin;
	int swidth = b + p.left() + m.left() + m.right() + p.right() + b;
	int sheight = b + p.top() + m.top() + m.bottom() + p.bottom() + b;
	return BSize(swidth, sheight);
}
BSize BWidget::shellSize(PartFlag part) const
{
	int b = member.border;
	const BPerch& p = member.perch;
	const BMargin& m = member.margin;
	if (part == Part_LeftTop)
	{
		int sleft = b + p.left() + m.left();
		int stop = b + p.top() + m.top();
		return BSize(sleft, stop);
	}
	if (part == Part_RightTop)
	{
		int sright = m.right() + p.right() + b;
		int stop = b + p.top() + m.top();
		return BSize(sright, stop);
	}
	if (part == Part_LeftBottom)
	{
		int sleft = b + p.left() + m.left();
		int sbottom = m.bottom() + p.bottom() + b;
		return BSize(sleft, sbottom);
	}
	if (part == Part_RightBottom)
	{
		int sright = m.right() + p.right() + b;
		int sbottom = m.bottom() + p.bottom() + b;
		return BSize(sright, sbottom);
	}
	if (part == Part_Left)
	{
		int sleft = b + p.left() + m.left();
		int sheight = b + p.top() + m.top() + m.bottom() + p.bottom() + b;
		return BSize(sleft, sheight);
	}
	if (part == Part_Right)
	{
		int sleft = p.right() + m.right() + b;
		int sheight = b + p.top() + m.top() + m.bottom() + p.bottom() + b;
		return BSize(sleft, sheight);
	}
	if (part == Part_Top)
	{
		int swidth = b + p.left() + m.left() + m.right() + p.right() + b;
		int stop = b + p.top() + m.top();
		return BSize(swidth, stop);
	}
	if (part == Part_Bottom)
	{
		int swidth = b + p.left() + m.left() + m.right() + p.right() + b;
		int sbottom = m.top() + p.top() + b;
		return BSize(swidth, sbottom);
	}
	int swidth = b + p.left() + m.left() + m.right() + p.right() + b;
	int sheight = b + p.top() + m.top() + m.bottom() + p.bottom() + b;
	return BSize(swidth, sheight);
}

BSize BWidget::sizeLimit(const BSize& size) const
{
	BSize sizeHint = this->sizeHint();
	BSize minSize = member.minSize;
	BSize maxSize = member.maxSize;
	BSizePolicy sizePolicy = member.sizePolicy;

	BSize baseSize;
	if (sizePolicy.widthPolicy() & Policy_Fixed)
		baseSize.width() = member.fixedSize.width();
	if (sizePolicy.widthPolicy() & Policy_Preferred)
		baseSize.width() = sizeHint.width();
	if (sizePolicy.heightPolicy() & Policy_Fixed)
		baseSize.height() = member.fixedSize.height();
	if (sizePolicy.heightPolicy() & Policy_Preferred)
		baseSize.height() = sizeHint.height();

	if (!(sizePolicy.widthPolicy() & Policy_Expanding) && maxSize.width() > baseSize.width())
		maxSize.width() = baseSize.width();
	if (!(sizePolicy.widthPolicy() & Policy_Shrinking) && minSize.width() < baseSize.width())
		minSize.width() = baseSize.width();
	if (!(sizePolicy.heightPolicy() & Policy_Expanding) && maxSize.height() > baseSize.height())
		maxSize.height() = baseSize.height();
	if (!(sizePolicy.heightPolicy() & Policy_Shrinking) && minSize.height() < baseSize.height())
		minSize.height() = baseSize.height();

	BSize temp = size;
	temp.limit(minSize, maxSize);
	return temp;
}
BSize BWidget::adaptSize(const BSize& size) const
{
	BSize asize = size;
	if (asize.width() == 0)
		asize.width() = member.size.width();
	if (asize.height() == 0)
		asize.height() = member.size.height();

	BSize hsize = this->sizeHint();

	if (member.sizePolicy.widthPolicy() & Policy_Preferred)
		asize.width() = hsize.width();
	if (member.sizePolicy.widthPolicy() & Policy_Fixed)
		asize.width() = member.fixedSize.width();

	if (member.sizePolicy.heightPolicy() & Policy_Preferred)
		asize.height() = hsize.height();
	if (member.sizePolicy.heightPolicy() & Policy_Fixed)
		asize.height() = member.fixedSize.height();

	asize.limit(member.minSize, member.maxSize);
	return asize;
}

BSize BWidget::sizeHint() const
{
	return preferSize(BSize());
}

bool BWidget::catchPoint(const BPoint& point) const
{
	if (IRound* round = member.round)
	{
		return round->containPoint(point);
	}
	return BRect(member.size).contain(point);
}

bool BWidget::input(const BString& text, const BValue& value)
{
	if (text == "title")
	{
		const BString& title = value;
		this->setTitle(title);
		return true;
	}
	if (text == "icon")
	{
		this->setIcon(value);
		return true;
	}
	return BObject::input(text, value);
}
bool BWidget::query(const BString& text, BValue& value) const
{
	if (text == "title")
	{
		value = member.title;
		return true;
	}
	if (text == "trans-title")
	{
		value = member.t_title;
		return true;
	}
	if (text == "icon")
	{
		value = member.icon;
		return true;
	}
	if (text == "round-border-points")
	{
		BPointfArray& points = value.fill<BPointfArray>();
		if (member.round)
			points = member.round->borderPoints;
		else
			points.clear();
		return true;
	}
	if (text == "round-perch-points")
	{
		BPointfArray& points = value.fill<BPointfArray>();
		if (member.round)
			points = member.round->perchPoints;
		else
			points.clear();
		return true;
	}
	if (text == "round-margin-points")
	{
		BPointfArray& points = value.fill<BPointfArray>();
		if (member.round)
			points = member.round->marginPoints;
		else
			points.clear();
		return true;
	}
	if (text == "round-center-points")
	{
		BPointfArray& points = value.fill<BPointfArray>();
		if (member.round)
			points = member.round->centerPoints;
		else
			points.clear();
		return true;
	}
	if (text == "round-background-points")
	{
		BPointfArray& points = value.fill<BPointfArray>();
		if (member.round)
			points = member.round->backgroundPoints;
		else
			points.clear();
		return true;
	}
	if (text == "upper-layout")
	{
		value = member.upperLayout;
		return true;
	}
	if (text == "screen")
	{
#ifdef linux
		value = member.window->screen;
#endif
		return true;
	}
	if (text == "window")
	{
		if (member.window)
		{
#ifdef linux
			value = member.window->hwnd;
#endif
#ifdef _WIN32
			value = member.window->hwnd;
#endif
		}
		return true;
	}
	return BObject::query(text, value);
}

bool BWidget::capture(BImage* image)
{
	if (!image || member.size.empty())
		return false;
	Format format = image->format();
	if (format == Format_None)
	{
		format = Format_RGBA;
		image->setFormat(format);
	}
	image->setSize(member.size);
	BByteArray* pixels = image->pixels();
	if (format == Format_RGBA && pixels)
	{
		glReadPixels(0, 0, member.size.width(), member.size.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels->data());
	}
	if (format == Format_RGB && pixels)
	{
		glReadPixels(0, 0, member.size.width(), member.size.height(), GL_RGB, GL_UNSIGNED_BYTE, pixels->data());
	}
	image->dirty();
	return true;
}
bool BWidget::capture(BImage* image, const BRect& rect)
{
	if (!image || rect.empty() || member.size.empty())
		return false;
	Format format = image->format();
	if (format == Format_None)
	{
		format = Format_RGBA;
		image->setFormat(format);
	}
	image->setSize(rect.size());
	BByteArray* pixels = image->pixels();
	int y = member.size.height() - rect.y() - rect.height();
	if (format == Format_RGBA && pixels)
	{
		glReadPixels(rect.x(), y, rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels->data());
	}
	if (format == Format_RGB && pixels)
	{
		glReadPixels(rect.x(), y, rect.width(), rect.height(), GL_RGB, GL_UNSIGNED_BYTE, pixels->data());
	}
	image->dirty();
	return true;
}

BPixmap* BWidget::pixmap()
{
	BWidget* root = this->root();
	return widget_member(root)->pixmap;
}
const BPixmap* BWidget::pixmap() const
{
	const BWidget* root = this->root();
	return widget_member(root)->pixmap;
}

BWidget* BWidget::root()
{
	BWidget* widget = this;
	while (widget_member(widget)->parent)
		widget = widget_member(widget)->parent;
	return widget;
}
const BWidget* BWidget::root() const
{
	const BWidget* widget = this;
	while (widget_member(widget)->parent)
		widget = widget_member(widget)->parent;
	return widget;
}

bool BWidget::setParent(BWidget* parent)
{
	if (member.parent != parent && parent != this)
	{
		BHolder<BWidget> holder;
		if (member.parent)
		{
			holder = this;
			if (!member.parent->removeChild(this))
				return false;
		}
		if (parent)
		{
			if (!parent->addChild(this))
				return false;
			holder = 0;
		}
		return true;
	}
	return false;
}
BWidget* BWidget::parent()
{
	return member.parent;
}
const BWidget* BWidget::parent() const
{
	return member.parent;
}

BWidget* BWidget::parent(const BString& name)
{
	BWidget* parent = this->parent();
	while (parent && parent->name() != name)
		parent = parent->parent();
	return parent;
}
const BWidget* BWidget::parent(const BString& name) const
{
	const BWidget* parent = this->parent();
	while (parent && parent->name() != name)
		parent = parent->parent();
	return parent;
}

bool BWidget::addChild(BWidget* child)
{
	if (child && this != child && !member.children.contain(child))
	{
		member.children.append(child);
		if (widget_member(child)->parent)
		{
			widget_member(child)->parent->removeChild(child);
		}
		widget_member(child)->parent = this;
		if (widget_member(child)->window)
		{
			widget_member(child)->window->boss = 0;
			widget_member(child)->window->hideWindow();
			widget_member(child)->window = 0;
			//widget_member(child)->clearLayer();
		}
		if (widget_member(child)->visible && widget_member(child)->state.shown)
		{
			BEvent event(Event_Show);
			widget_member(child)->procEvent(event);
		}
		widget_member(child)->freshEnabled(member.state.enabled);
		widget_member(child)->dirtyStyle = true;
		object_member(child)->emit(Signal_ParentChanged, BValue(this, true));
		this->emit(Signal_Insert, BValue(child, this));
		return true;
	}
	return false;
}
bool BWidget::removeChild(BWidget* child)
{
	if (child && this != child && widget_member(child)->parent == this)
	{
		BHolder<BWidget> holder(child);
		widget_member(child)->parent = 0;
		BWidget* root = this->root();
		if (IWindow* window = widget_member(root)->window)
		{
			if (widget_member(child)->focused)
				window->focus(this);
			if (window->popupWidgets.contain(this))
				window->popup(child, false);
			//widget_member(child)->clearLayer();
		}
		if (widget_member(child)->visible && widget_member(child)->state.shown)
		{
			BEvent event(Event_Hide);
			widget_member(child)->procEvent(event);
		}
		BLayout* layout = widget_member(child)->upperLayout;
		if (layout && layout_member(layout)->host == this)
		{
			layout->remove(child);
		}
		member.children.remove(child);
		object_member(child)->emit(Signal_ParentChanged);
		this->emit(Signal_Remove, BValue(child, this));
		return true;
	}
	return false;
}
void BWidget::clearChildren()
{
	if (member.children.size())
	{
		while (BWidget* child = member.children.last())
		{
			this->removeChild(child);
		}
		this->emit(Signal_Clear);
		this->fresh();
	}
}

int BWidget::childCount() const
{
	return member.children.size();
}
BWidget* BWidget::child(int index)
{
	return member.children(index);
}
const BWidget* BWidget::child(int index) const
{
	return member.children(index);
}

BWidget* BWidget::child(const BString& name)
{
	for (int i = 0; i < member.children.size(); i++)
	{
		BWidget* child = member.children[i];
		if (child->name() == name)
			return child;
	}
	return 0;
}
const BWidget* BWidget::child(const BString& name) const
{
	for (int i = 0; i < member.children.size(); i++)
	{
		BWidget* child = member.children[i];
		if (child->name() == name)
			return child;
	}
	return 0;
}

BWidget* BWidget::find(const BString& name)
{
	if (this->name() == name)
		return this;
	for (int i = 0; i < member.children.size(); i++)
	{
		BWidget* child = member.children[i];
		BWidget* result = child->find(name);
		if (result)
			return result;
	}
	return 0;
}
const BWidget* BWidget::find(const BString& name) const
{
	if (this->name() == name)
		return this;
	for (int i = 0; i < member.children.size(); i++)
	{
		BWidget* child = member.children[i];
		BWidget* result = child->find(name);
		if (result)
			return result;
	}
	return 0;
}

bool BWidget::setIndex(int index)
{
	if (BWidget* parent = member.parent)
	{
		BArray<BWidgetHolder>& children = widget_member(parent)->children;
		int pos = children.find(this);
		if (children.move(pos, index))
		{
			int min = bMin(pos, index);
			int max = bMax(pos, index);
			for (int i = min; i <= max; i++)
			{
				BWidget* widget = children[i];
				widget->emit(Signal_OrderChanged, i);
			}
			return true;
		}
	}
	if (BPixmap* pixmap = member.pixmap)
	{
		BArray<BWidgetHolder>& widgets = pixmap_member(pixmap)->widgets;
		int pos = widgets.find(this);
		if (widgets.move(pos, index))
		{
			int min = bMin(pos, index);
			int max = bMax(pos, index);
			for (int i = min; i <= max; i++)
			{
				BWidget* widget = widgets[i];
				widget->emit(Signal_OrderChanged, i);
			}
			return true;
		}
	}
	return false;
}
int BWidget::index() const
{
	if (BWidget* parent = member.parent)
	{
		BArray<BWidgetHolder>& children = widget_member(parent)->children;
		return children.find(this);
	}
	if (BPixmap* pixmap = member.pixmap)
	{
		BArray<BWidgetHolder>& widgets = pixmap_member(pixmap)->widgets;
		return widgets.find(this);
	}
	return -1;
}

BWidget* BWidget::prev()
{
	if (BWidget* parent = member.parent)
	{
		BArray<BWidgetHolder>& children = widget_member(parent)->children;
		int pos = children.find(this);
		return children.at(pos - 1);
	}
	if (BPixmap* pixmap = member.pixmap)
	{
		BArray<BWidgetHolder>& widgets = pixmap_member(pixmap)->widgets;
		int pos = widgets.find(this);
		return widgets.at(pos - 1);
	}
	return 0;
}
const BWidget* BWidget::prev() const
{
	if (BWidget* parent = member.parent)
	{
		BArray<BWidgetHolder>& children = widget_member(parent)->children;
		int pos = children.find(this);
		return children.at(pos - 1);
	}
	if (BPixmap* pixmap = member.pixmap)
	{
		BArray<BWidgetHolder>& widgets = pixmap_member(pixmap)->widgets;
		int pos = widgets.find(this);
		return widgets.at(pos - 1);
	}
	return 0;
}
BWidget* BWidget::next()
{
	if (BWidget* parent = member.parent)
	{
		BArray<BWidgetHolder>& children = widget_member(parent)->children;
		int pos = children.find(this);
		return children.at(pos + 1);
	}
	if (BPixmap* pixmap = member.pixmap)
	{
		BArray<BWidgetHolder>& widgets = pixmap_member(pixmap)->widgets;
		int pos = widgets.find(this);
		return widgets.at(pos + 1);
	}
	return 0;
}
const BWidget* BWidget::next() const
{
	if (BWidget* parent = member.parent)
	{
		BArray<BWidgetHolder>& children = widget_member(parent)->children;
		int pos = children.find(this);
		return children.at(pos + 1);
	}
	if (BPixmap* pixmap = member.pixmap)
	{
		BArray<BWidgetHolder>& widgets = pixmap_member(pixmap)->widgets;
		int pos = widgets.find(this);
		return widgets.at(pos + 1);
	}
	return 0;
}

bool BWidget::above(const BWidget* other) const
{
	if (!other || this == other)
		return false;
	BWidget* parent = widget_member(other)->parent;
	while (parent)
	{
		if (parent == this)
			return true;
		parent = widget_member(parent)->parent;
	}
	return false;
}
bool BWidget::under(const BWidget* other) const
{
	if (!other || this == other)
		return false;
	BWidget* parent = member.parent;
	while (parent)
	{
		if (parent == other)
			return true;
		parent = widget_member(parent)->parent;
	}
	return false;
}
bool BWidget::contain(const BWidget* widget) const
{
	if (this == widget)
		return false;
	for (int i = 0; i < member.children.size(); i++)
	{
		BWidget* child = member.children[i];
		if (child == widget)
			return true;
	}
	return false;
}

void BWidget::event(const BEvent& event)
{
	switch (event.type())
	{
	case Event_Show:
		this->showEvent(event);
		break;
	case Event_Hide:
		this->hideEvent(event);
		break;
	case Event_Popup:
		this->popupEvent(event);
		break;
	case Event_Close:
		this->closeEvent(event);
		break;

	case Event_Move:
		this->moveEvent(event);
		break;
	case Event_Resize:
		this->resizeEvent(event);
		break;
	case Event_Update:
		this->updateEvent(event);
		break;
	case Event_Adjust:
		this->adjustEvent(event);
		break;

	case Event_Style:
		this->styleEvent(event);
		break;
	case Event_Fresh:
		this->freshEvent(event);
		break;
	case Event_Paint:
		this->paintEvent(event);
		break;

	case Event_Active:
		this->activeEvent(event);
		break;
	case Event_Hover:
		this->hoverEvent(event);
		break;
	case Event_Focus:
		this->focusEvent(event);
		break;
	case Event_Input:
		this->inputEvent(event);
		break;

	case Event_KeyPress:
		this->keyPressEvent((const BKeyEvent&)event);
		break;
	case Event_KeyRelease:
		this->keyReleaseEvent((const BKeyEvent&)event);
		break;

	case Event_MouseEnter:
		this->mouseEnterEvent((const BMouseEvent&)event);
		break;
	case Event_MouseLeave:
		this->mouseLeaveEvent((const BMouseEvent&)event);
		break;
	case Event_MousePress:
		this->mousePressEvent((const BMouseEvent&)event);
		break;
	case Event_MouseRelease:
		this->mouseReleaseEvent((const BMouseEvent&)event);
		break;
	case Event_MouseMove:
		this->mouseMoveEvent((const BMouseEvent&)event);
		break;
	case Event_MouseDrag:
		this->mouseDragEvent((const BMouseEvent&)event);
		break;
	case Event_MouseWheel:
		this->mouseWheelEvent((const BMouseEvent&)event);
		break;
	case Event_MouseClick:
		this->mouseClickEvent((const BMouseEvent&)event);
		break;
	case Event_DoubleClick:
		this->mouseDoubleClickEvent((const BMouseEvent&)event);
		break;

	case Event_DragEnter:
		this->dragEnterEvent((const BMouseEvent&)event);
		break;
	case Event_DragLeave:
		this->dragLeaveEvent((const BMouseEvent&)event);
		break;
	case Event_DragMove:
		this->dragMoveEvent((const BMouseEvent&)event);
		break;
	case Event_DragDrop:
		this->dragDropEvent((const BMouseEvent&)event);
		break;
	default:
		break;
	}
}

void BWidget::showEvent(const BEvent& event)
{
	if (this->checks(Signal_Show))
	{
		this->emit(Signal_Show, BValue(true, &event));
	}
}
void BWidget::hideEvent(const BEvent& event)
{
	if (this->checks(Signal_Hide))
	{
		this->emit(Signal_Hide, BValue(false, &event));
	}
}
void BWidget::popupEvent(const BEvent& event)
{
	if (!event.accepted() && event.value())
	{
		this->setFocused(true);
	}
	if (this->checks(Signal_Popup))
	{
		this->emit(Signal_Popup, BValue(event.value(), &event));
	}
}
void BWidget::closeEvent(const BEvent& event)
{
	this->hide();
	if (IWindow* window = member.window)
	{
		if (app_coreWidget && widget_member(app_coreWidget)->window == window)
		{
			BApplication::exit();
			return;
		}
		if (window == app_windows.first())
		{
			BApplication::exit();
			return;
		}
	}
}

void BWidget::moveEvent(const BEvent& event)
{
	if (this->checks(Signal_Moved))
	{
		this->emit(Signal_Moved, BValue(member.pos, &event));
	}
}
void BWidget::resizeEvent(const BEvent& event)
{
	if (this->checks(Signal_Resized))
	{
		this->emit(Signal_Resized, BValue(member.size, &event));
	}
}
void BWidget::updateEvent(const BEvent& event)
{
	if (this->checks(Signal_Updated))
	{
		this->emit(Signal_Updated, BValue(event.value(), &event));
	}
}
void BWidget::adjustEvent(const BEvent& event)
{
	if (this->checks(Signal_Adjust))
	{
		this->emit(Signal_Adjust, BValue(event.value(), &event));
	}
}

void BWidget::styleEvent(const BEvent& event)
{
	if (this->checks(Signal_Styled))
	{
		this->emit(Signal_Styled, BValue(event.value(), &event));
	}
}
void BWidget::freshEvent(const BEvent& event)
{
	if (this->checks(Signal_Freshed))
	{
		this->emit(Signal_Freshed, BValue(event.value(), &event));
	}
}
void BWidget::paintEvent(const BEvent& event)
{
	BPainter painter(this);
	painter.drawBackground();
	painter.drawForeground();
	painter.drawPerch();
	painter.drawMargin();
	painter.drawBorder();
}

void BWidget::activeEvent(const BEvent& event)
{
	if (this->checks(Signal_Actived))
	{
		this->emit(Signal_Actived, BValue(member.state.actived, &event));
	}
}
void BWidget::hoverEvent(const BEvent& event)
{
	if (this->checks(Signal_Hovered))
	{
		this->emit(Signal_Hovered, BValue(member.state.hovered, &event));
	}
}
void BWidget::focusEvent(const BEvent& event)
{
	if (this->checks(Signal_Focused))
	{
		this->emit(Signal_Focused, BValue(member.focused, &event));
	}
}
void BWidget::inputEvent(const BEvent& event)
{
	if (this->checks(Signal_Input))
	{
		this->emit(Signal_Input, BValue(event.value(), &event));
	}
}

void BWidget::keyPressEvent(const BKeyEvent& keyEvent)
{
	if (this->checks(Signal_KeyPress))
	{
		this->emit(Signal_KeyPress, BValue(keyEvent.key(), &keyEvent));
	}
}
void BWidget::keyReleaseEvent(const BKeyEvent& keyEvent)
{
	if (this->checks(Signal_KeyRelease))
	{
		this->emit(Signal_KeyRelease, BValue(keyEvent.key(), &keyEvent));
	}
}

void BWidget::mouseEnterEvent(const BMouseEvent& mouseEvent)
{
	if (this->checks(Signal_MouseEnter))
	{
		this->emit(Signal_MouseEnter, BValue(mouseEvent.pos(), &mouseEvent));
	}
}
void BWidget::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{
	if (this->checks(Signal_MouseLeave))
	{
		this->emit(Signal_MouseLeave, BValue(mouseEvent.pos(), &mouseEvent));
	}
}
void BWidget::mousePressEvent(const BMouseEvent& mouseEvent)
{
	if (this->checks(Signal_Pressed))
	{
		this->emit(Signal_Pressed, BValue(mouseEvent.pos(), &mouseEvent));
	}
}
void BWidget::mouseReleaseEvent(const BMouseEvent& mouseEvent)
{
	if (this->checks(Signal_Released))
	{
		this->emit(Signal_Released, BValue(mouseEvent.pos(), &mouseEvent));
	}
}
void BWidget::mouseMoveEvent(const BMouseEvent& mouseEvent)
{
	if (this->checks(Signal_MouseMoved))
	{
		this->emit(Signal_MouseMoved, BValue(mouseEvent.pos(), &mouseEvent));
	}
}
void BWidget::mouseDragEvent(const BMouseEvent& mouseEvent)
{
	if (mouseEvent.button() == Button_Left)
	{
		if (this->checks(Signal_Dragged))
		{
			this->emit(Signal_Dragged, BValue(mouseEvent.pos(), &mouseEvent));
		}
	}
	if (mouseEvent.button() == Button_Right)
	{
		if (this->checks(Signal_RightDragged))
		{
			this->emit(Signal_RightDragged, BValue(mouseEvent.pos(), &mouseEvent));
		}
	}
}
void BWidget::mouseWheelEvent(const BMouseEvent& mouseEvent)
{
	if (this->checks(Signal_Wheeled))
	{
		this->emit(Signal_Wheeled, BValue(mouseEvent.wheel(), &mouseEvent));
	}
}
void BWidget::mouseClickEvent(const BMouseEvent& mouseEvent)
{
	if (mouseEvent.button() == Button_Left)
	{
		if (this->checks(Signal_Clicked))
		{
			this->emit(Signal_Clicked, BValue(mouseEvent.pos(), &mouseEvent));
		}
	}
	if (mouseEvent.button() == Button_Right)
	{
		if (this->checks(Signal_RightClicked))
		{
			this->emit(Signal_RightClicked, BValue(mouseEvent.pos(), &mouseEvent));
		}
	}
}
void BWidget::mouseDoubleClickEvent(const BMouseEvent& mouseEvent)
{
	if (this->checks(Signal_DoubleClicked))
	{
		this->emit(Signal_DoubleClicked, BValue(mouseEvent.pos(), &mouseEvent));
	}
}

void BWidget::dragEnterEvent(const BMouseEvent& mouseEvent)
{
	if (this->checks(Signal_DragEnter))
	{
		this->emit(Signal_DragEnter, BValue(mouseEvent.value(), &mouseEvent));
	}
}
void BWidget::dragLeaveEvent(const BMouseEvent& mouseEvent)
{
	if (this->checks(Signal_DragLeave))
	{
		this->emit(Signal_DragLeave, BValue(mouseEvent.value(), &mouseEvent));
	}
}
void BWidget::dragMoveEvent(const BMouseEvent& mouseEvent)
{
	if (this->checks(Signal_DragMoved))
	{
		this->emit(Signal_DragMoved, BValue(mouseEvent.value(), &mouseEvent));
	}
}
void BWidget::dragDropEvent(const BMouseEvent& mouseEvent)
{
	if (this->checks(Signal_DragDropped))
	{
		this->emit(Signal_DragDropped, BValue(mouseEvent.value(), &mouseEvent));
	}
}
